﻿using System;
using System.IO;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

namespace Crocodoc
{
    /// <summary>
    /// Represents an error/exception returned from the Crocodoc service.
    /// </summary>
    public class CrocodocException : Exception
    {
        /// <summary>
        /// Gets the short string representing the error code.
        /// </summary>
        public string Code
        {
            get;
            private set;
        }

        /// <summary>
        /// The status code.
        /// </summary>
        public HttpStatusCode StatusCode
        {
            get;
            private set;
        }

        /// <summary>
        /// The error message returned from the crocodoc service.
        /// </summary>
        public string WebError
        {
            get;
            private set;
        }

        /// <summary>
        /// The Contructor taking a WebException.
        /// </summary>
        /// <param name="exception">The WebException thrown when communicating with the Crocodoc REST API.</param>
        public CrocodocException(WebException exception)
            : base(exception.Message, exception)
        {
            StatusCode = ((HttpWebResponse)exception.Response).StatusCode;
            Code = ((HttpWebResponse)exception.Response).StatusDescription;

            using (Stream stream = exception.Response.GetResponseStream())
            {
                
                try
                {
                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(CrocodocError));
                    CrocodocError error = (CrocodocError)serializer.ReadObject(stream);

                    WebError = error.Error;
                }
                catch
                {
                    // Error deserializing response.
                }

                // Response wasn't deserialized to crocodoc error or no error was found, just set WebError as the response string.
                if (String.IsNullOrEmpty(WebError))
                {
                    using (StreamReader reader = new StreamReader(stream))
                    {
                        WebError = reader.ReadToEnd();
                    }
                }
            }
        }

        /// <summary>
        /// The constructor for CrocodocException.
        /// </summary>
        /// <param name="message">A string representing the long form error message.</param>
        /// <param name="code">A string representing the short form error code.</param>
        public CrocodocException(string message, string code)
            : base(message)
        {
            Code = code;
        }

        /// <summary>
        /// Class representing the error in the web response when a WebException is thrown.
        /// </summary>
        [DataContract]
        private class CrocodocError
        {
            /// <summary>
            /// The error message.
            /// </summary>
            [DataMember(Name="error")]
            public string Error
            {
                get;
                set;
            }
        }
    }
}
